package com.hy;

import java.util.Arrays;

/**
 * Created With IntelliJ IDEA.
 * Descriptions:1463. 摘樱桃 II
 * <p>
 * 给你一个 rows x cols 的矩阵 grid 来表示一块樱桃地。 grid 中每个格子的数字表示你能获得的樱桃数目。
 * 你有两个机器人帮你收集樱桃，机器人 1 从左上角格子 (0,0) 出发，机器人 2 从右上角格子 (0, cols-1) 出发。
 * 请你按照如下规则，返回两个机器人能收集的最多樱桃数目：
 * 从格子 (i,j) 出发，机器人可以移动到格子 (i+1, j-1)，(i+1, j) 或者 (i+1, j+1) 。
 * 当一个机器人经过某个格子时，它会把该格子内所有的樱桃都摘走，然后这个位置会变成空格子，即没有樱桃的格子。
 * 当两个机器人同时到达同一个格子时，它们中只有一个可以摘到樱桃。
 * 两个机器人在任意时刻都不能移动到 grid 外面。
 * 两个机器人最后都要到达 grid 最底下一行。
 * <p>
 * User:Mr.Du
 * Date:2024/5/7
 * Time:10:27
 */
public class CherryPickupII {

    public int cherryPickup(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int[][][] memos = new int[m][n][n];
        for(int[][] memo : memos){
            for(int[] cur : memo){
                Arrays.fill(cur, -1);
            }
        }
        return dfs(0, 0, n - 1, m, n, grid, memos);
    }

    // 定义 dfs(i,j,k) 表示 A 从 (i,j) 出发，B 从 (i,k) 出发，
    // 到达最后一行，可以得到的樱桃个数的最大值。

    public int dfs(int i, int j, int k, int m, int n, int[][] grid, int[][][] memos){
        if(i == m || j < 0 || j == n || k < 0 || k == n) return 0;
        if(memos[i][j][k] != -1) return memos[i][j][k];
        int res = 0;
        for(int j2 = j - 1;j2 < j + 2;j2++){
            for(int k2 = k - 1;k2 < k + 2;k2++){
                res = Math.max(res, dfs(i + 1, j2, k2, m, n, grid, memos));
            }
        }
        res += grid[i][j] + (k != j? grid[i][k] : 0);
        memos[i][j][k] = res;
        return res;
    }

    public int dps(int[][] grid){
        int m = grid.length;
        int n = grid[0].length;
        int[][][] f = new int[m + 1][n + 2][n + 2];
        for (int i = m - 1; i >= 0; i--) {
            for (int j = 0; j < Math.min(n, i + 1); j++) {
                for (int k = Math.max(j + 1, n - 1 - i); k < n; k++) {
                    f[i][j + 1][k + 1] = max(
                            f[i + 1][j][k], f[i + 1][j][k + 1], f[i + 1][j][k + 2],
                            f[i + 1][j + 1][k], f[i + 1][j + 1][k + 1], f[i + 1][j + 1][k + 2],
                            f[i + 1][j + 2][k], f[i + 1][j + 2][k + 1], f[i + 1][j + 2][k + 2]
                    ) + grid[i][j] + grid[i][k];
                }
            }
        }
        return f[0][1][n];
    }

    private int max(int x, int... y) {
        for (int v : y) {
            x = Math.max(x, v);
        }
        return x;
    }
}
